﻿using System;
using System.Collections.Generic;
using NetFramework;
using USClientKernel.Template;
using Game.Kernel;
using Game.Logic.Handler;
using Game.Logic.Data;

namespace Game.Logic.Manager
{
    public class GameDataManager : Singleton<GameDataManager>
    {
        private static ulong m_maxGuid = 0;
        public static ulong MaxGUID { get => m_maxGuid; }
        private static ulong GeneratorGUID() { return ++m_maxGuid; }

        private Dictionary<GameDataType, List<GameBaseData>> m_dictGameDatas;
        public Dictionary<GameDataType, List<GameBaseData>> GameDataLists { get => m_dictGameDatas; }

        private GameDataHandler m_handler;
        public GameDataHandler Handler { get => m_handler; private set => m_handler = value; }

        protected override void Init()
        {
            m_dictGameDatas = new Dictionary<GameDataType, List<GameBaseData>>();
            InitDataHandler();
        }

        private void InitDataHandler()
        {
            Handler = new GameDataHandler();
            NetworkManager.Instance.RegisterSocketListener(Handler);
        }


        # region Register Data
        public void RegisterGameData(GameBaseData _gameData)
        {
            if (null == _gameData)
                throw new Exception("try to register a null GameData!");
            if (GameDataType.Invalid == _gameData.DataType)
                return;
            RegisterGameData(_gameData.DataType, _gameData);
        }


        public void RegisterGameData(GameDataType _dataType, GameBaseData _gameData)
        {
            GameDataLists.TryGetValue(_dataType, out List<GameBaseData> gdl);

            if (null == gdl)
            {
                gdl = new List<GameBaseData>();
                GameDataLists.Add(_dataType, gdl);
            }

            if (gdl.Contains(_gameData))
            {
                return;
            }
            gdl.Add(_gameData);
            _gameData.SetGuid(GeneratorGUID());
            _gameData.SetDataIndex(gdl.Count-1);
        }


        public void UnregisterGameData(GameBaseData _gameData)
        {
            if (GameDataType.Invalid == _gameData.DataType)
                return;
            UnregisterGameData(_gameData.DataType, _gameData);
        }


        public void UnregisterGameData(GameDataType _dataType, GameBaseData _gameData)
        {
            GameDataLists.TryGetValue(_dataType, out List<GameBaseData> gdl);
            if (null == gdl)
                return;
            gdl.Remove(_gameData);
        }


        public List<GameBaseData> GetGameDataList(GameDataType _dataType)
        {
            GameDataLists.TryGetValue(_dataType, out List<GameBaseData> gdl);
            return gdl;
        }


        public GameBaseData GetGameData(GameDataType _dataType)
        {
            GameDataLists.TryGetValue(_dataType, out List<GameBaseData> gdl);
            if (null == gdl)
                return null;

            if (gdl.Count < 1)
                return null;
            else
                return gdl[0];
        }


        public T GetGameData<T>(GameDataType _dataType) where T : GameBaseData
        {
            return GetGameData(_dataType) as T;
        }


        public GameBaseData GetGameData(GameDataType _dataType, ulong _guid)
        {
            List<GameBaseData> gdl = GetGameDataList(_dataType);
            if (null == gdl)
                return null;

            GameBaseData rt = null;
            foreach (GameBaseData item in gdl)
            {
                if (_guid == item.GUID)
                {
                    rt = item;
                    break;
                }
            }

            return rt;
        }

        public T GetGameData<T>(GameDataType _dataType, ulong _guid) where T : GameBaseData
        {
            return GetGameData(_dataType, _guid) as T;
        }
        #endregion


        #region Server Data Listener

        public void RegisterServerDataListener(string _protoName, OnReceivedServer _handler)
        {
            m_handler.RegisterDataListener(_protoName, _handler);
        }

        public void UnregisterServerDataListener(string _protoName, OnReceivedServer _handler)
        {
            m_handler.UnregisterDataListener(_protoName, _handler);
        }

        #endregion
    }
}
